package cn.sciento.iam.saas.app.service.impl;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.sciento.core.exception.CommonException;
import org.apache.commons.collections4.CollectionUtils;
import cn.sciento.core.base.BaseAppService;
import cn.sciento.iam.domain.entity.TenantConfig;
import cn.sciento.iam.domain.repository.TenantConfigRepository;
import cn.sciento.iam.saas.app.service.TenantConfigService;
import cn.sciento.mybatis.common.Criteria;
import cn.sciento.mybatis.helper.SecurityTokenHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TenantConfigServiceImpl extends BaseAppService implements TenantConfigService {
  @Autowired
  private TenantConfigRepository tenantConfigRepository;
  
  @Override
  public List<TenantConfig> getTenantConfigList(Long tenantId) {
    return this.tenantConfigRepository.select((new TenantConfig()).setTenantId(tenantId));
  }
  
  @Override
  @Transactional(rollbackFor = {Exception.class})
  public List<TenantConfig> createOrUpdateTenantConfigs(Long tenantId, List<TenantConfig> tenantConfigs) {
    if (CollectionUtils.isEmpty(tenantConfigs) || tenantId == null) {
      return tenantConfigs;
    }
    tenantConfigs.forEach(tenantConfig -> tenantConfig.setTenantId(tenantId));
    validList(tenantConfigs);
    SecurityTokenHelper.validTokenIgnoreInsert(tenantConfigs);
    Map<Boolean, List<TenantConfig>> insertOrUpdate = tenantConfigs.stream().collect(
        Collectors.partitioningBy(tenantConfig -> (tenantConfig.getObjectVersionNumber() != null)));
    List<TenantConfig> updateConfigs = insertOrUpdate.get(Boolean.TRUE);
    List<TenantConfig> insertConfigs = insertOrUpdate.get(Boolean.FALSE);
    if (CollectionUtils.isNotEmpty(updateConfigs)) {
      this.tenantConfigRepository.batchUpdateOptional(updateConfigs, "configValue");
    }
    if (CollectionUtils.isNotEmpty(insertConfigs)) {
      insertConfigs.forEach(tenantConfig -> {
            validateParams(tenantConfig);
            this.tenantConfigRepository.insertSelective(tenantConfig);
          });
    }
    return tenantConfigs;
  }
  
  @Override
  public List<TenantConfig> getTenantConfigs(Long tenantId, String configKey) {
    return this.tenantConfigRepository.selectOptional((new TenantConfig()).setTenantId(tenantId).setConfigKey(configKey), (new Criteria())
        .select(TenantConfig.SELECT_FIELDS));
  }
  
  private void validateParams(TenantConfig tenantConfig) {
    int count = this.tenantConfigRepository.selectCount((new TenantConfig()).setTenantId(tenantConfig.getTenantId())
        .setConfigKey(tenantConfig.getConfigKey()));
    if (count > 0) {
      throw new CommonException("error.data_exists");
    }
  }
}
